﻿using System.ComponentModel;
using System.Text.RegularExpressions;

namespace Swimj.Core.Extensions
{
    public static class EnumExtensions
    {
        public static T ToEnum<T>(this string input) where T : struct
        {
            return input.MapTo<T>();
        }

        public static T ToEnum<T>(this int intValue) where T : Enum
        {
            return intValue.MapTo<T>();
        }

        public static string GetDescription(this Enum enumValue)
        {
            object[] attr = enumValue.GetType().GetField(enumValue.ToString())!
                .GetCustomAttributes(typeof(DescriptionAttribute), false);
            if (attr.Length > 0)
                return ((DescriptionAttribute)attr[0]).Description;
            string result = enumValue.ToString();
            result = Regex.Replace(result, "([a-z])([A-Z])", "$1 $2");
            result = Regex.Replace(result, "([A-Za-z])([0-9])", "$1 $2");
            result = Regex.Replace(result, "([0-9])([A-Za-z])", "$1 $2");
            result = Regex.Replace(result, "(?<!^)(?<! )([A-Z][a-z])", " $1");
            return result;
        }

        public static List<string> GetDescriptionList(this Enum enumValue)
        {
            string result = enumValue.GetDescription();
            return result.Split(',').ToList();
        }

        public static IDictionary<string, object> ToDictionary<TEnum>()
        {
            return Enum.GetValues(typeof(TEnum))
                .Cast<TEnum>()
                .ToDictionary(enumValue => enumValue.ToString(), enumValue => (object)Convert.ToInt32(enumValue));
        }

        public static IDictionary<string, object> ToDictionary(Type enumType, Func<Enum, object> valueConverterFunc = null,
            Func<object, string> nameConverterFunc = null)
        {
            if (valueConverterFunc == null)
                valueConverterFunc = o => Convert.ToInt32(o) as object;

            if (nameConverterFunc == null)
                nameConverterFunc = o => o.ToString();

            var result = new Dictionary<string, object>();

            foreach (var val in Enum.GetValues(enumType).Cast<object>()
                         .Where(val => !result.ContainsKey(nameConverterFunc(val))))
                result.Add(nameConverterFunc(val), valueConverterFunc((Enum)val));

            return result;
        }
    }
}